#include "test.h"
#include <initializer_list>
#include <hashtable.h>
//#include <bits/stl_tree.h>

namespace Test
{
void TestC::test_fork()
{
    pid_t pid;
    printf("befor: pid is %d\n", getpid());
    //if((pid = fork()) == -1)
    {
        perror("fork()");
    }
    printf("After:pid is %d,fork return %d\n", getpid(), pid);
    sleep(1);
}

void TestC::test_pointer()
{
    int i = 0, *p = &i;
    printf("step 1: i=%d, &i=%d, p=%d *p=%d\n", i, &i, p, *p);
    *p++;
    printf("step 3: i=%d, &i=%d, p=%d *p=%d\n", i, &i, p, *p);
    (*p)++;
    printf("step 2: i=%d, &i=%d, p=%d *p=%d\n", i, &i, p, *p);
    printf("step 4: p - &i=%d\n", p - &i);
}

void TestC::test_template_template_parameter()
{
    XCls<std::string, Vec> c1;
    XCls<std::string, List> c2;
}

void TestC::test_lambda()
{
    auto cmp = [](int a, int b) {
        return true;
    };
    //  lambda没有默认构造函数和默认复制构造函数
    std::set<int, decltype(cmp)> test_set(cmp);
    test_set.insert(2);
    test_set.insert(1);
    test_set.insert(3);

    std::map<std::string, int> coll = {{"a", 1}, {"b", 2}, {"c", 3}};
    int sum = std::accumulate(coll.begin(), coll.end(),
                              0,
                              std::bind(std::plus<int>(),
                                        std::placeholders::_1,
                                        std::bind(&std::map<std::string, int>::value_type::second,
                                                  std::placeholders::_2)));
    std::cout << sum << std::endl;

    int sum2 = std::accumulate(coll.begin(), coll.end(),
                               0, [](int a, std::map<std::string, int>::value_type b) -> int {
                                   return a + b.second * 2;
                               });
    std::cout << sum2 << std::endl;
}

void TestC::test_tuple()
{
    Tuple<int32_t, std::string, char, float> tp(0, "cba", 'd', 1.012);
    std::cout << tp.head() << " " 
        << tp.tail().head() << " " 
        << tp.tail().tail().head() << " "
        << tp.tail().tail().tail().head() << std::endl;
}

void TestC::test_foreach()
{
    std::map<int32_t, void *> mp;
    std::vector<std::pair<int32_t, void *>> vec;
    for (int32_t i = 0; i < 30000000; ++i)
    {
        mp.emplace(i, nullptr);
    }
    for (int32_t i = 0; i < 30000000; ++i)
    {
        vec.emplace_back(i, nullptr);
    }

    std::cout << "start test..." << std::endl;

    std::time_t start = std::time(NULL);
    for (auto &it : vec)
    {
        // DoSomething
    }
    std::cout << "[std::vector] time passed: "
              << std::difftime(std::time(NULL), start) << " s.\n";

    start = std::time(NULL);
    for (auto &it : mp)
    {
        // DoSomething
    }
    std::cout << "[std::map] time passed: "
              << std::difftime(std::time(NULL), start) << " s.\n";
}

struct EmptyStruct
{};

struct eqstr {
    bool operator() (const char s1, const char s2) const
    {
        // return strcmp(s1, s2) == 0;
        return s1 == s2;
    }
};

void TestC::test_container()
{
    std::function<void(void)> func = []() -> void {};
    std::map<char, char> mp;
    std::set<char> st;

    std::cout << "sizeof(std::function<void(void)>)=" << sizeof(std::function<void(void)>) << std::endl;
    std::cout << "sizeof(func)=" << sizeof(func) << std::endl;

    std::cout << "sizeof(std::map<char, char>)=" << sizeof(std::map<char, char>) << std::endl;
    std::cout << "sizeof(std::set<char>)=" <<  sizeof(std::set<char>) << std::endl;

    std::_Rb_tree<int32_t, int32_t, std::_Identity<int32_t>, std::less<int32_t>> rb;

    std::cout << "sizeof(_Rb_tree_color)=" << sizeof(std::_Rb_tree_color::_S_black) << std::endl;

    std::cout << "sizeof(_Rb_tree<...>)=" << sizeof(rb) << std::endl;

    auto it = rb._M_insert_equal(1);
    it = rb._M_insert_equal(1);
    std::cout << *it << std::endl;
    std::cout << rb.size() << std::endl;
    auto p = rb._M_insert_unique(1);
    std::cout << p.second << std::endl;

    std::unordered_set<int32_t> un_st;
    un_st.insert(0);
    std::cout << "bucket_size(0)=" << un_st.bucket_size(0) << std::endl;

    std::cout << "sizeof(EmptyStruct)=" << sizeof(EmptyStruct) << std::endl;

    // std::__uset_hashtable<char, 
    //                 std::hash<char>, 
    //                 eqstr, 
    //                 char, 
    //                 std::allocator<char>> ht;

    std::hash<std::string>();
}

void TestC::test_cplusplus()
{
    std::cout << __cplusplus << std::endl;
}

void TestC::test_func()
{
    std::cout << __func__ << std::endl;
    // 在源代码中插入当前源代码行号
    std::cout << __LINE__ << std::endl;
    // 在源文件中插入当前源文件名
    std::cout << __FILE__ << std::endl;
    // 在源文件中插入当前的编译日期
    std::cout << __DATE__ << std::endl;
    // 在源文件中插入当前编译时间
    std::cout << __TIME__ << std::endl;
    // 当要求程序严格遵循ANSI C标准时该标识被赋值为1
    std::cout << __STDC__ << std::endl;
    // 当编写C++程序时该标识符被定义
    std::cout << __cplusplus << std::endl;
}

void TestC::add_log(LogActionTag tag)
{
    std::cout << __func__ << " " << typeid(tag).name() << std::endl;
}

void TestC::add_log(LogBattleTag tag)
{
    std::cout << __func__ << " " << typeid(tag).name() << std::endl;
}

void TestC::test_files()
{
    std::vector<std::string> files;
    std::string path = "E:/Downloads";
    get_files(path, files);
    for (auto &it: files)
    {
        if (it.find("PPPD") != std::string::npos)
        {
            //std::cout << it << std::endl;
        }
        std::cout << it << std::endl;
    }
}

void TestC::get_files(std::string path, std::vector<std::string>& files)  
{  
    //文件句柄  
    long   hFile   =   0;  
    //文件信息  
    struct _finddata_t fileinfo;  
    std::string p;  
    if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) !=  -1)  
    {  
        do  
        {  
            //如果是目录,迭代之  
            //如果不是,加入列表  
            if((fileinfo.attrib &  _A_SUBDIR))  
            {  
                if(strcmp(fileinfo.name,".") != 0  &&  strcmp(fileinfo.name,"..") != 0)
                {
                    get_files( p.assign(path).append("\\").append(fileinfo.name), files );  
                }
            }  
            else  
            {  
                files.emplace_back(p.assign(path).append("\\").append(fileinfo.name) );  
            }  
        }while(_findnext(hFile, &fileinfo)  == 0);  
        _findclose(hFile);  
    }  
}

} // namespace Test